﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeCloud.WeChatSDK
{
    /// <summary>
    /// 验证服务器地址的有效性
    /// 该类对接口检验方法进行封装，调用名为Check的静态方法，即可实现接口校验。
    /// </summary>
    public static class CheckSignature
    {
        /// <summary>
        /// 网站没有提供Token(或传入为null)的情况下的默认Token
        /// </summary>
        public const string Token = "CodeCloud";

        /// <summary>
        /// 校验签名是否正确
        /// </summary>
        /// <param name="signture">微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <param name="token">随机字符串</param>
        /// <returns></returns>
        public static bool Check(string signture,string timestamp,string nonce,string token)
        {
            return signture == GetSignture(timestamp,nonce,token);
        }

        /// <summary>
        /// 放回本地生成的签名
        /// </summary>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <param name="token">随机字符串</param>
        /// <returns></returns>
        public static string GetSignture(string timestamp, string nonce, string token)
        {
            token = token ?? Token;
            //将token、timestamp、nonce三个参数进行字典序排序
            string[] arr = new[] { token, timestamp, nonce }.OrderBy(z => z).ToArray();
            //将三个参数字符串拼接成一个字符串
            string arrString = string.Join("", arr);
            //使用.Net FrameWork 提供的System.Security.Cryptography.SHA1类来实现sha1加密
            System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create();
            byte[] sha1arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            //sha1 加密后的结果是一个byte数组，因此还需将加密结果转换为字符串
            StringBuilder enText = new StringBuilder();
            foreach (var b in sha1arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            //返回加密签名
            return enText.ToString();
        }


        #region 使用示例

        ///// <summary>
        ///// 处理微信服务器验证消息
        ///// </summary>
        //private void Auth()
        //{
        //    string signture = Request["signture"];
        //    string timestamp = Request["timestamp"];
        //    string nonce = Request["nonce"];
        //    string echostr = Request["echostr"];
        //    if(Request.HttpMothod == "GET")
        //    {
        //        if (CheckSignature.Check(signture, timestamp, nonce,Token))
        //        {
        //            WriteContent(echostr);
        //        }
        //        else
        //        {
        //            WriteContent("failed:"+ signture+","+ CheckSignature.GetSignture(timestamp, nonce, Token)+"。"+"如果你在浏览器中看到这句话，说明此地址可以被座位微信公众号后台的URL，请注意保持Token一致。");
        //        }
        //    }
        //}

        #endregion
    }
}
